/**
 * token中间件模块
 * 提供token验证功能，包括access token和refresh token
 */

const jwt = require('jsonwebtoken');
const { getLogger } = require('../logger');
const logger = getLogger('middlewares.authMiddleware');
const {jwtConfig} = require('../../config');
const Token = require("../models/tokenModel");
const { unauthorized, badRequest } = require('../utils/response');

// 验证access token中间件
const authenticateToken = async (req, res, next) => {
    const authHeader = req.headers['authorization'];
    const token = authHeader && authHeader.split(' ')[1];

    if (!token) {
        return unauthorized(req, res, '缺少认证token');
    }

    try {
        // 验证token签名和过期时间，使用jwtUtils中的密钥
        const decoded = jwt.verify(token, jwtConfig.secret, { algorithms: [jwtConfig.algorithm] });

        // 检查token是否在数据库中且未过期
        const [tokens] = await Token.checkTokenValid(token,'access')
        
        if (tokens.length === 0) {
            return unauthorized(req, res, '无效的access token');
        }

        req.user = {
            ...decoded,
            tokenData: tokens
        };
        
        // 更新token最后活动时间（不阻塞主流程）
        try {
            await Token.updateLastActiveTime(token);
        } catch (updateError) {
            logger.error('更新token最后活动时间失败', { error: updateError });
            // 不影响认证流程，继续执行
        }
        
        next();
    } catch (error) {
        if (error.name === 'TokenExpiredError') {
            return unauthorized(req, res, 'access token已过期');
        } else {
            return unauthorized(req, res, '无效的access token');
        }
    }
};


// 验证refresh token中间件
const authenticateRefreshToken = async (req, res, next) => {
    
    const { refreshToken } = req.body;

    if (!refreshToken) {
        return badRequest(req, res, 'refreshToken不能为空');
    }

    try {
        // 验证refresh token，使用jwtUtils中的密钥
        const decoded = jwt.verify(refreshToken, jwtConfig.refreshSecret, { algorithms: [jwtConfig.algorithm] });

        // 检查refresh token是否有效
        // 检查token是否在数据库中且未过期
        const tokens = await Token.checkTokenValid(refreshToken,'refresh')
        
        if (!tokens || tokens.length === 0) {
            return unauthorized(req, res, '无效的refresh token');
        }

        req.refreshTokenData = tokens[0];
        
        // 更新refresh token最后活动时间（不阻塞主流程）
        try {
            await Token.updateLastActiveTime(refreshToken);
        } catch (updateError) {
            logger.error('更新refresh token最后活动时间失败', { error: updateError });
            // 不影响认证流程，继续执行
        }
        
        next();
    } catch (error) {
        return unauthorized(req, res, '无效的refresh token');
        
        
    }
};



// 验证码验证中间件
const verifyCaptcha = (req, res, next) => {
    const { captcha } = req.body;
    
    // 检查是否提供了验证码
    if (!captcha) {
        return badRequest(req, res, '请输入验证码');
    }
    
    // 检查会话中是否存在验证码
    if (!req.session.captcha) {
        return badRequest(req, res, '验证码已过期，请重新获取');
    }
    
    // 检查验证码是否过期（5分钟）
    const captchaTime = req.session.captchaTime;
    const now = Date.now();
    const fiveMinutes = 5 * 60 * 1000; // 5分钟
    
    if (!captchaTime || (now - captchaTime) > fiveMinutes) {
        // 清除过期的验证码
        delete req.session.captcha;
        delete req.session.captchaTime;
        
        return badRequest(req, res, '验证码已过期，请重新获取');
        
        
    }
    
    // 验证码比较（不区分大小写）
    if (captcha.toLowerCase() !== req.session.captcha) {
        return badRequest(req, res, '验证码错误');
    }
    
    // 验证成功后清除验证码
    delete req.session.captcha;
    delete req.session.captchaTime;
    
    next();
};


// 验证SSE token中间件
const authsseToken = async (req, res, next) => {
    // 优先从query string获取token
    let token = req.query.token || '';
    
    // 如果query string中没有token，尝试从Authorization header获取
    if (!token && req.headers['authorization']) {
        const authHeader = req.headers['authorization'];
        // 支持 Bearer token 格式
        if (authHeader.startsWith('Bearer ')) {
            token = authHeader.split(' ')[1];
        } else {
            // 也支持直接在header中放置token
            token = authHeader;
        }
    }

    if (!token) {
        logger.warn('SSE认证失败：缺少token', { path: req.path, method: req.method });
        return unauthorized(req, res, '缺少认证token');
    }

    try {
        // 验证token签名和过期时间，使用jwtUtils中的密钥
        const decoded = jwt.verify(token, jwtConfig.secret, { algorithms: [jwtConfig.algorithm] });

        // 检查token是否在数据库中且未过期
        const [tokens] = await Token.checkTokenValid(token, 'access');
        
        if (!tokens || tokens.length === 0) {
            logger.warn('SSE认证失败：数据库中不存在有效token', { userId: decoded.userId });
            return unauthorized(req, res, '无效的access token');
        }

        req.user = {
            ...decoded,
            tokenData: tokens
        };
        
        // 更新token最后活动时间（不阻塞主流程）
        try {
            await Token.updateLastActiveTime(token);
        } catch (updateError) {
            logger.error('更新SSE token最后活动时间失败', { error: updateError.message });
            // 不影响认证流程，继续执行
        }
        
        logger.info('SSE认证成功', { userId: decoded.userId });
        next();
    } catch (error) {
        logger.error('SSE token验证失败', { error: error, tokenLength: token.length > 0 ? token.length : 0 });
        if (error.name === 'TokenExpiredError') {
            return unauthorized(req, res, 'access token已过期');
        } else {
            return unauthorized(req, res, '无效的access token');
        }
    }
};

module.exports = { authenticateToken, authenticateRefreshToken, verifyCaptcha ,authsseToken};